from manimlib import *

class UpdatersExample(Scene):
  def construct(self):
    # self.embed()
    square = Square()
    square.set_fill(BLUE_E, 1)
    brace = always_redraw(Brace, square, UP)
    text, number = label = VGroup(
      Text("width = "),
      # DecimalNumber 是一个可变数字，通过将其拆成一个个 Tex 字符来加快速度
      DecimalNumber(
        0,
        show_ellipsis = True,
        num_decimal_places = 2,
        include_sign = True
      )
    )
    label.arrange(RIGHT)
    # always(f, x) 表示每帧都执行 f(x)
    always(label.next_to, brace, UP)

    # f_always(f, g) 类似 always，每帧都执行 f(g())
    f_always(number.set_value, square.get_width)
    self.add(square, brace, label)

    self.play(
      square.animate.scale(2),
      rate_func = there_and_back,
      run_time = 2
    )
    self.wait()

    self.play(
      square.animate.set_width(5, stretch = True),
      run_time = 3
    )
    self.wait()

    self.play(
      square.animate.set_width(2),
      run_time = 3
    )
    self.wait()

    now = self.time
    w0 = square.get_width()

    # add_updater() 为该物体设置一个更新函数
    square.add_updater(
      lambda m: m.set_width(w0 * math.sin(self.time - now) + w0)
    )
    self.wait(4 * PI)